/**
 * @file jq-validate-bs-form.js
 * @author betgar (betgar@163.com)
 * @date 10/05/2018
 * @time 15:09:02
 * @description jquery validation integrated with bootstrap form element.
 */
define([
  'jquery',
  'lodash',
  './jq-validate-methods'
], function ($, lodash, validateMethods) {
  // var validatorDefaults = $.extend(true, {}, validator.defaults);
  /**
   *
   * @param {HTMLElement | Selector | jQuery} ele - 元素
   * @returns {formGroup: jQuery, feedback: jQuery, hasFeedback: Function, hasFormGroup: Function}
   */
  var findRelations = function (ele) {
    var $element = $(ele), elementType = $element.attr('type'), $ele;
    if (elementType === 'checkbox' || elementType === 'radio') {
      $ele = $('[name=' + $element.attr('name') + ']');
    } else {
      $ele = $element;
    }
    var $formGroup = $ele.closest('.form-group'),
      $feedback = $formGroup.find('.form-control-feedback');
    return {
      formGroup: $formGroup,
      feedback: $feedback,
      hasFeedback: function () {
        return !!$feedback.length;
      },
      hasFormGroup: function () {
        return !!$formGroup.length;
      },
      lodashtoggleClassWithProp: function (prop, options) {
        this[prop].addClass(options.addClass || '').removeClass(options.removeClass || '');
      },
      /**
       * @param {addClass: string, removeClass: string} options - 配置项
       *
       */
      feedbackToggleClass: function (options) {
        if (this.hasFeedback()) {
          this.lodashtoggleClassWithProp('feedback', options);
        }
      },
      /**
       * @param {addClass: string, removeClass: string} options - 配置项
       *
       */
      formGroupToggleClass: function (options) {
        this.lodashtoggleClassWithProp('formGroup', options);
      }
    };
  };
  var commonOptions = {
    ignoreTitle: true,
    errorElement: 'span',
    errorPlacement: function (error, element) {
      var feedbackData;
      relations = findRelations(element);
      error.addClass('help-block');
      relations.formGroup.find('.help-block').replaceWith(error);
      if (relations.hasFeedback()) {
        feedbackData = relations.feedback.data();
        relations.feedbackToggleClass({
          addClass: feedbackData.invalidClass || 'glyphicon-remove'
        });
      }
    },
    success: function (label, element) {
      var feedbackData;
      relations = findRelations(element);
      if (relations.hasFeedback()) {
        feedbackData = relations.feedback.data();
        relations.feedbackToggleClass({
          addClass: feedbackData.invalidClass || 'glyphicon-remove'
        });
      }
    },
    highlight: function (element, errorClass, validClass) {
      var feedbackData;
      relations = findRelations(element);
      relations.formGroupToggleClass({
        addClass: 'has-error',
        removeClass: 'has-success'
      });
      if (relations.hasFeedback()) {
        feedbackData = relations.feedback.data();
        relations.feedbackToggleClass({
          addClass: feedbackData.invalidClass || 'glyphicon-remove',
          removeClass: feedbackData.validClass || "glyphicon-ok"
        });
      }
    },
    unhighlight: function (element, errorClass, validClass) {
      var feedbackData;
      relations = findRelations(element);
      relations.formGroupToggleClass({
        addClass: 'has-success',
        removeClass: 'has-error'
      });
      if (relations.hasFeedback()) {
        feedbackData = relations.feedback.data();
        relations.feedbackToggleClass({
          addClass: feedbackData.validClass || "glyphicon-ok",
          removeClass: feedbackData.invalidClass || 'glyphicon-remove'
        });
      }
    }
  };


  var composer = {
    /**
   * @param  {Object []} options - $.validator.defaults结构对象
   * @param  {String} prop - 属性.
   * @returns {Function}
   */
    composeFunc: function (options, prop) {
      return function () {
        var context = this, args = lodash.slice(arguments);
        lodash.each(lodash.map(options, prop), function (handler) {
          if (lodash.isFunction(handler)) {
            handler.apply(context, args);
          }
        });
      }
    },
    /**
     * 组合options中相同的属性.
     * @param  {Object[]} options - options集合.
     * @param  {String[]} props - 属性.
     */
    composeWith: function (options, props) {
      var composedOptions = {}, context = this;
      lodash.each(props, function (prop) {
        composedOptions[prop] = context.composeFunc(options, prop);
      });
      return composedOptions;
    }
  }

  var props = ['success', 'highlight', 'unhighlight', 'errorPlacement'];
  var combinedOptions = lodash.extend({}, commonOptions, composer.composeWith([commonOptions], props));

  return {
    /**
     * 获取validator使用的options.
     * @returns {Object} options集合.
     */
    validatorOptions: function () {
      return combinedOptions;
    },
    findRelations: findRelations
  };
});
